package com.tree.common.controller;

import com.alibaba.fastjson.JSONException;
import com.tree.common.constants.ErrorCodeConstants;
import com.tree.common.dto.FrontResponse;
import com.tree.common.exception.BizException;
import com.tree.common.mail.service.IEmailService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.TypeMismatchException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.MessageSource;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.support.MissingServletRequestPartException;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;

/**
 * @ClassName com.demo.common.controller
 * Description: <类功能描述>. <br>
 * <p>
 * <使用说明>
 * </p>
 * @Author tree
 * @Date 2019-05-25 23:46
 * @Version 1.0
 */
@RestControllerAdvice("com.demo")
public class ExceptionHandlerController {

    private static final Logger logger = LoggerFactory.getLogger(ExceptionHandlerController.class);

    private static final Logger exceptionLogger = LoggerFactory.getLogger("com.demo.exception");


    @Resource
    protected MessageSource messageSource;

    @Autowired
    private IEmailService emailService;

    @Value("${mail.exception.to:tree317035791@163.com}")
    private String mailTo;

    @ExceptionHandler(BizException.class)
    public FrontResponse handleBizException(BizException bizE){
        logger.error(bizE.getMessage(),bizE);
        FrontResponse frontResponse = new FrontResponse();
        frontResponse.setCode(bizE.getCode());
        frontResponse.setMessage(bizE.getMessage());
        return frontResponse;
    }

    @ExceptionHandler({BindException.class,TypeMismatchException.class,MissingServletRequestParameterException.class
        ,MissingServletRequestPartException.class,MethodArgumentNotValidException.class})
    public FrontResponse handleSpringDataBindingException(Exception e){
        String message = "参数不合法";

        if(e instanceof BindException){
            List<ObjectError> errorList = ((BindException) e).getAllErrors();
            if(errorList.size() > 0){
                message = messageSource.getMessage(errorList.get(0),null);
            }
        }else if(e instanceof TypeMismatchException ){
            message = String.format("参数【%s】的值不合法：%s",((TypeMismatchException)e).getValue(),((TypeMismatchException)e).getPropertyName());
        }else if(e instanceof MissingServletRequestParameterException ){

        }else if(e instanceof MissingServletRequestPartException){

        }else  if(e instanceof MethodArgumentNotValidException){
            MethodArgumentNotValidException me = (MethodArgumentNotValidException)e;
            BindingResult bindingResult = me.getBindingResult();
            List<ObjectError> errorList = bindingResult.getAllErrors();
            if(CollectionUtils.isEmpty(errorList)){
                message = messageSource.getMessage(errorList.get(0),null);
            }

        }

        logger.error(message,e);
        return new FrontResponse(ErrorCodeConstants.FAIL,message);
    }

    @ExceptionHandler({JSONException.class})
    public FrontResponse handleJsonException(JSONException e){
        logger.error("参数不合法",e);
        return new FrontResponse(ErrorCodeConstants.FAIL,"参数不合法");
    }

    @ExceptionHandler({Throwable.class})
    public FrontResponse handleThrowable(Throwable e){
        exceptionLogger.error("参数不合法",e);
        sendExceptionMail(e);
        return new FrontResponse(ErrorCodeConstants.FAIL,"参数不合法");
    }

    private void sendExceptionMail(Throwable t) {
        StringWriter writer = null;
        try{
            String[] addresses = mailTo.split(",");
            InetAddress address = InetAddress.getLocalHost();
            String ip = address.getHostAddress();
            writer = new StringWriter();
            t.printStackTrace(new PrintWriter(writer));
            String exception = writer.toString();
            emailService.sendMail(addresses,"exception subject"+":"+ip,"exception info: "+exception);
        }catch (UnknownHostException e1){

        }catch (Exception e){

        }finally {
            if(writer != null ){
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


}
